package com.thinvent.nj.ais.inteceptor;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.thinvent.nj.common.util.StringUtil;
import com.thinvent.nj.common.util.WebContextUtil;
import com.thinvent.nj.ais.entity.Resource;
import com.thinvent.nj.ais.entity.User;
import com.thinvent.nj.ais.shiro.UserContextUtil;
import org.springframework.cache.Cache;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author liupeijun
 */
@Component
public class MenuInteceptor implements HandlerInterceptor {

    @javax.annotation.Resource(name = "defaultCache")
    private Cache cache;


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse httpServletResponse, Object o) throws Exception {

        try {
            // 非HttpGet请求直接忽略
            if (!HttpMethod.GET.name().equalsIgnoreCase(request.getMethod())) {
                return true;
            }

            // ajax请求直接忽略
            if (WebContextUtil.isAjaxRequest(request)) {
                return true;
            }

            String relativeUrl = WebContextUtil.getRelativeUrl(request);

            // 当前请求是获取静态资源，错误请求等直接忽略
            if ("/".equals(relativeUrl)
                    || relativeUrl.startsWith("/js")
                    || relativeUrl.startsWith("/css")
                    || relativeUrl.startsWith("/fonts")
                    || relativeUrl.startsWith("/image")
                    || relativeUrl.startsWith("/static")
                    || relativeUrl.startsWith("/error")
                    || relativeUrl.startsWith("/layout")) {
                return true;
            }


            String cacheKey = MenuInteceptor.class.getName() + "_preHandle_" + relativeUrl;

            Map<String, Object> map = cache.get(cacheKey, Map.class);

            if (map != null) {
                request.setAttribute("CURRENT_SELECT_MENU_ID", map.get("id"));
                request.setAttribute("CURRENT_SELECT_MENU_IDS", map.get("ids"));
                request.setAttribute("BREAD_CRUMB", map.get("names"));

                return true;
            }


            User user = UserContextUtil.currentUser();

            List<Map<String, Object>> resources = user.getMenus();
            Map<String, Object> target = findTargetResource(relativeUrl, resources);

            if (target != null) {
                request.setAttribute("CURRENT_SELECT_MENU_ID", target.get("id"));
                Map<String, List<String>> breadCrumb = getBreadCrumb(target, user.getResourceList());
                request.setAttribute("CURRENT_SELECT_MENU_IDS", breadCrumb.get("ids").toString());
                request.setAttribute("BREAD_CRUMB", breadCrumb.get("names"));

                Map<String, Object> cacheMap = new HashMap<>(3);
                cacheMap.put("id", target.get("id"));
                cacheMap.put("ids", breadCrumb.get("ids").toString());
                cacheMap.put("names", breadCrumb.get("names"));

                cache.put(cacheKey, cacheMap);
            }

            return true;
        } catch (Exception e) {
            // 该拦截器仅用于菜单选中和面包屑显示，如有异常可以忽略
        }

        return true;
    }

    private Map<String, List<String>> getBreadCrumb(Map<String, Object> target, List<Resource> resources) {

        List<String> ids = Lists.newArrayList();
        List<String> names = Lists.newArrayList();

        ids.add(String.valueOf(target.get("id")));
        names.add((String) target.get("name"));

        rescusiveSearch(String.valueOf(target.get("pId")), resources, ids, names);

        Collections.reverse(ids);
        Collections.reverse(names);

        Map<String, List<String>> result = Maps.newHashMap();
        result.put("ids", ids);
        result.put("names", names);
        return result;
    }

    private void rescusiveSearch(String pId, List<Resource> resources, List<String> ids, List<String> names) {
        Resource pResource = null;
        for (Resource item : resources) {
            if (String.valueOf(item.getId()).equals(pId)) {
                pResource = item;
                break;
            }
        }

        if (pResource != null) {
            ids.add(String.valueOf(pResource.getId()));
            names.add(pResource.getName());

            pId = String.valueOf(pResource.getpId());
            rescusiveSearch(pId, resources, ids, names);
        }

    }

    private Map<String,Object> findTargetResource(String servletPath, List<Map<String, Object>> resources) {
        String uri;
        for (Map<String, Object> item : resources) {
            uri = (String) item.get("uri");
            if (!StringUtil.isNullOrEmpty(uri) && uri.endsWith(servletPath)) {
                return item;
            }

             List<Map<String, Object>> children = (List<Map<String, Object>>)item.get("children");
            if (children != null && children.size() > 0) {
                Map<String, Object> result =  findTargetResource(servletPath, children);

                if (result != null) {
                    return result;
                }
            }
        }

        return null;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}